#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <dirent.h>
#include <string.h>
#include <arpa/inet.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <fcntl.h>

#define LEN 4096
#define MAXLINE	40
#define BUFFERSIZE 4096
#define PORT 55330
#define LENGTH_OF_LISTEN_QUEUE 20

/*将buf中的字节内容写入文件描述符fd*/
ssize_t writen(int fd, const void * vptr, size_t n)
{
    size_t nleft;
    ssize_t nwritten;
    const char * ptr;

    ptr = vptr;
    nleft = n;
    while ( nleft > 0)
    {
        if ((nwritten = write(fd, ptr, nleft)) <= 0)
        {
            if (nwritten < 0 && errno == EINTR)
            {
                nwritten = 0;
            }
            else
            {
                return -1;
            }
        }

        nleft -= nwritten;
        ptr += nwritten;
    }
    return n;
}


ssize_t readline(int fd, void * vptr, size_t maxlen)
{
    ssize_t    n, rc;
    char    c, *ptr;

    ptr = vptr;
    for (n = 1; n < maxlen; n++)
    {
again:
        if ((rc = read(fd, &c, 1)) == 1)
        {
            *ptr++ = c;
            if (c == '\n')
            {
                break;
            }
        }
        else if (rc == 0)
        {
            *ptr = 0;
            return (n - 1);
        }
        else
        {
            if (errno == EINTR)
            {
                goto again;
            }
            return (-1);
        }
    }

    *ptr = 0;
    return (n);
}

int *getCharNum(char *filename, int *totalNum){
    FILE *fp;  
    char buffer[1003]; 
    int bufferLen;
    int i;  
    char c; 
    int isLastBlank = 0; 
    int charNum = 0; 
    int wordNum = 0; 
    if( (fp=fopen(filename, "rb")) == NULL ){
        perror(filename);
        return NULL;
    }
    while(fgets(buffer, 1003, fp) != NULL){
        bufferLen = strlen(buffer);
        // 遍历缓冲区的内容
        for(i=0; i<bufferLen; i++){
            c = buffer[i];
            if( c==' ' || c=='\t'){ 
                !isLastBlank && wordNum++; 
                isLastBlank = 1;
            }else if(c!='\n'&&c!='\r'){ 
                charNum++; 
                isLastBlank = 0;
            }
        }
        !isLastBlank && wordNum++; 
        isLastBlank = 1; 
        totalNum[0] += wordNum;  // 总单词数
        charNum = 0;
        wordNum = 0;
    }
    return totalNum;
}

int main(void)
{
    int	server_socket_fd, connfd;
    char	buff[BUFFERSIZE + 1];
    char	filename[BUFFERSIZE + 1];
    char	cd[BUFFERSIZE+1];
    char	choose[10];
    struct sockaddr_in	server_addr, cliaddr;
    int	cliaddrlen;
    int	filefd;  
    int	count;
    DIR	*dir;
    struct dirent	*ptr;
  
    bzero(&server_addr, sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(PORT);

// 创建socket，若成功，返回socket描述符 
  server_socket_fd = socket(AF_INET, SOCK_STREAM, 0); 
  if(server_socket_fd < 0) 
  { 
    perror("Create Socket Failed:"); 
    exit(1); 
  } 
  int opt = 1; 
  setsockopt(server_socket_fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)); 
  
  // 绑定socket和socket地址结构 
  if(-1 == (bind(server_socket_fd, (struct sockaddr*)&server_addr, sizeof(server_addr)))) 
  { 
    perror("Server Bind Failed:"); 
    exit(1); 
  } 
    
  // socket监听 
  if(-1 == (listen(server_socket_fd, LENGTH_OF_LISTEN_QUEUE))) 
  { 
    perror("Server Listen Failed:"); 
    exit(1); 
  }

    while(1)
    {
        printf("Listenning...\n");

        cliaddrlen = sizeof(cliaddr);
        connfd = accept(server_socket_fd, (struct sockaddr *)&cliaddr, &cliaddrlen);
        if (readline(connfd, buff, BUFFERSIZE) < 0)
        {
            fprintf(stderr, "readline error\n");
            exit(1);
        }
        buff[strlen(buff) - 1] = 0;    /* change '\n' to NUL */
        memcpy(filename, buff, BUFFERSIZE + 1);
        printf("The file name is: %s\n", buff);

        //change the direct to store the file
        printf("Input the direct you want to store %s:\n", buff);
        scanf("%s", cd);
        if(chdir(cd) < 0)
        {
            fprintf(stderr, "direct error\n");
            exit(1);
        }

        dir = opendir(cd);
        while((ptr = readdir(dir)) != NULL)
        {
            if(strcmp(buff, ptr->d_name) == 0)
            {
                printf("Exist file：%s\n", buff);
                printf("Do you want rename the file? please input yes or no\n");
                scanf("%s", choose);
                if(strcmp(choose, "yes") == 0)
                {
                    printf("Rename:\t");
                    scanf("%s", buff);
                }
                else
                {
                    printf("Exist, exit！\n");
                    exit (1);
                }

            }
        }

        filefd = open(buff, O_WRONLY | O_CREAT);
        if (filefd < 0)
        {
            fprintf(stderr, "can't open the file: %s\n", buff);
            exit(1);
        }


        while(count = read(connfd, buff, BUFFERSIZE))
        {
            if (count < 0)
            {
                fprintf(stderr, "connfd read error\n");
                exit(1);
            }
            if (writen(filefd, buff, count) < 0)
            {
                fprintf(stderr, "writing to filefd error\n");
                exit(1);
            }
        }
        closedir(dir);
        close(filefd);
        close(connfd);
        printf("file %s received!\n", filename);
	int totalNum[1] = {0};
	if(getCharNum(filename, totalNum)){
        printf("Total: %d words\n", totalNum[0]);
        }else{
        printf("Error!\n");
    }
}
    close(server_socket_fd);
    return 0;

}
